package com.shigu.linkage.processes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.opentae.data.mall.beans.*;
import com.opentae.data.mall.examples.MoPassagewayAccountExample;
import com.opentae.data.mall.examples.MoWxuserinfoExample;
import com.opentae.data.mall.interfaces.*;
import com.shigu.agent.exceptions.AgentException;
import com.shigu.agent.processes.AgentProcess;
import com.shigu.linkage.sdks.exceptions.LinkageException;
import com.shigu.linkage.sdks.requests.CardChangeRequest;
import com.shigu.linkage.sdks.requests.LinkageRequest;
import com.shigu.linkage.sdks.requests.ResetRateRequest;
import com.shigu.linkage.sdks.requests.SubMerchantRegistRequest;
import com.shigu.linkage.sdks.responses.CardChangeResponse;
import com.shigu.linkage.sdks.responses.ResetRateResponse;
import com.shigu.linkage.sdks.responses.SubMerchantRegistResponse;
import com.shigu.main4.common.util.MoneyUtil;
import com.shigu.main4.common.util.SecretUtil;
import com.shigu.passageway.Passageway;
import com.shigu.passageway.bo.RegistBO;
import com.shigu.passageway.exceptions.PassagewayException;
import com.shigu.wx.web.WxTempleateBaseData;
import com.shigu.wx.web.services.WxTokenService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 联动通道
 */
@Service("linkagePassageway")
public class LinkagePassageway implements Passageway {
    private static final Logger logger = LoggerFactory.getLogger(LinkagePassageway.class);
    private final Long passagewayId=3L;
    private final String merchantCode= LinkageRequest.merchantCode;

    @Autowired
    MoPassagewayMapper moPassagewayMapper;

    @Autowired
    MoPassagewayAccountMapper moPassagewayAccountMapper;

    @Autowired
    MoCardMapper moCardMapper;

    @Autowired
    MoOrderMapper moOrderMapper;

    @Autowired
    MoBankMapper moBankMapper;

    @Autowired
    MoSettlementMapper moSettlementMapper;

    @Autowired
    ManagerUserMapper managerUserMapper;

    @Autowired
    MoShareProfitMapper moShareProfitMapper;

    @Autowired
    AgentProcess agentProcess;

    @Autowired
    MoWxuserinfoMapper moWxuserinfoMapper;

    @Autowired
    MoBankLinknoMapper moBankLinknoMapper;

    @Autowired
    WxTokenService wxTokenService;

    private Double defaultRate;
    private Double systemRate;
    private Double cashMoney;

    private String merchantNotifyUrl;//商户进件结果回调

    @Value("${main_host}")
    private String MAIN_HOST;

    @Value("${me.flag}")
    private String OEM_FLAG;

    @Value("${wx.template.payed}")
    private String PAYED_NOTIFY;

    @Value("${wx.notify.admin}")
    private String ADMIN_NOTIFY;

    @PostConstruct
    public void init(){
        MoPassageway passageway=moPassagewayMapper.selectByPrimaryKey(passagewayId);
        defaultRate=Double.valueOf(passageway.getSysMax());
        systemRate=Double.valueOf(passageway.getSysMin());
        cashMoney=Double.valueOf(passageway.getCashMoney());
        merchantNotifyUrl=MAIN_HOST+"bus/merchantNotify.htm";
//        merchantNotifyUrl="http://kjt01.hz.taeapp.com/callbacktest.htm";
    }

    @Override
    public String regist(RegistBO bo) throws PassagewayException {
        Double rate=bo.getRate()==null||bo.getRate()<systemRate?defaultRate:bo.getRate();
        SubMerchantRegistRequest request=new SubMerchantRegistRequest();
        request.setMerchName(bo.getRealName());
        request.setNickName(bo.getRealName());
        request.setServicePhone(bo.getTelephone());
        request.setContacts(bo.getRealName());
        request.setContactsTel(bo.getTelephone());
        request.setContactMobile(bo.getTelephone());
        request.setContactAdress(bo.getBankLocation());
        request.setCategoryCode("205");
        request.setMerchantCode(merchantCode);
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHHmmss");
        DecimalFormat df=new DecimalFormat("000000");
        String subMchId=sdf.format(new Date())+df.format(bo.getUserId());
        request.setOutMerchantCode(subMchId);
        request.setAccNo(bo.getBankAccountNumber());
        request.setAccName(bo.getRealName());
        request.setAccType("D");
        request.setOpenBank(bo.getBankName());
        request.setAlliedBankCode(bo.getLinkno());
        request.setTradeRate(MoneyUtil.dealRate4(rate));
        request.setRemitFee(bo.getCashMoney()==null? MoneyUtil.formatMoney(cashMoney):bo.getCashMoney());
        request.setSettlePeriod("T0");
        String simpleName=moBankMapper.selSimpleNameByName(bo.getBankName());
        request.setBankCode(simpleName==null?"IABC":simpleName);
        request.setMerchantNotifyUrl(merchantNotifyUrl);
        request.setCertNo(bo.getIdCard());
        //需要bankCode
        request.setFastpayPointsTradeRate(MoneyUtil.dealRate4(rate));
        SubMerchantRegistResponse response=request.exec();
        if (!response.isSuccess()) {
            throw new LinkageException(response.getErrorMessage());
        }
        MoPassagewayAccount account=new MoPassagewayAccount();
        account.setTelephone(bo.getTelephone());
        account.setAreaCode(bo.getAreaCode());
        account.setAccountCode(subMchId);
        account.setRealName(bo.getRealName());
        account.setBankUser(bo.getRealName());
        account.setRate(MoneyUtil.dealRate4(rate));
        account.setPassagewayId(passagewayId);
        account.setUserId(bo.getUserId());
        account.setBankLocation(bo.getBankLocation());
        account.setBankName(bo.getBankName());
        account.setBankNumber(bo.getBankAccountNumber());
        account.setBodyNumber(bo.getIdCard());
        account.setUsedStatus(false);
        account.setCashMoney(bo.getCashMoney()==null?MoneyUtil.formatMoney(cashMoney):bo.getCashMoney());
        account.setLastModifyTime(new Date());
        account.setExamineStatus(1);
        moPassagewayAccountMapper.insertSelective(account);
        return subMchId;
    }

    @Override
    public String updateInfo(RegistBO bo) throws PassagewayException {
        //查出老账户
        MoPassagewayAccount account=moPassagewayAccountMapper.selByUserId(bo.getUserId(),passagewayId);
        CardChangeRequest request=new CardChangeRequest();
        request.setSubMerchantCode(account.getAccountCode());
        request.setMobileBank(bo.getTelephone());
        request.setAlliedBankCode(selLinkNum(bo.getBankAccountNumber()));
        //查联行号
        request.setAccNo(bo.getBankAccountNumber());
        request.setOpenBank(bo.getBankName());
        request.setMerchantCode(merchantCode);
        String simpleName=moBankMapper.selSimpleNameByName(bo.getBankName());
        request.setBankCode(simpleName==null?"IABC":simpleName);
        CardChangeResponse res=request.exec();
        if ("000000".equals(res.getErrorCode())) {
            MoPassagewayAccount yp=new MoPassagewayAccount();
            yp.setBankName(bo.getBankName());
            yp.setBankNumber(bo.getBankAccountNumber());
            yp.setBankLocation(bo.getBankLocation());
            yp.setAccountId(account.getAccountId());
            yp.setTelephone(bo.getTelephone());
            yp.setLastModifyTime(new Date());
            yp.setCashMoney(bo.getCashMoney()==null?MoneyUtil.formatMoney(cashMoney):bo.getCashMoney());
            moPassagewayAccountMapper.updateByPrimaryKeySelective(yp);
        }else{
            logger.error(JSON.toJSONString(request)+":"+res.resultBody());
        }
        return account.getAccountCode();
    }

    /**
     * 查联行号
     * @param bankNumber
     * @return
     */
    public String selLinkNum(String bankNumber){
        MoBankLinkno linkno=new MoBankLinkno();
        linkno.setBankCard(bankNumber);
        linkno=moBankLinknoMapper.selectOne(linkno);
        if (linkno != null) {
            return linkno.getLinkno();
        }
        return "123321123";
    }

    @Override
    public String toPay(Long userId, Long creditCardId, Double withdrawalMoney) throws PassagewayException {
        //查出本通道账户，查出信用卡
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(userId).andPassagewayIdEqualTo(passagewayId);
        List<MoPassagewayAccount> accounts=moPassagewayAccountMapper.selectByExample(accountExample);
        if (accounts.size()==0) {
            throw new LinkageException("请先激活通道");
        }
        MoPassagewayAccount account=accounts.get(0);
        MoCard card=moCardMapper.selectByPrimaryKey(creditCardId);
        if (card == null) {
            throw new LinkageException("无效信用卡");
        }
        MoOrder order=new MoOrder();
        order.setUserId(userId);
        order.setMcc("6301");
        order.setRate(account.getRate());
        order.setPassagewayId(passagewayId);
        order.setCreditIcon(card.getBankIcon());
        order.setCreditBank(card.getBankName());
        order.setMoney(MoneyUtil.formatMoney(withdrawalMoney));
        order.setMobileName(account.getTelephone());
        order.setCreditNo(card.getBankNo());
        order.setCashNo(account.getBankNumber());
        order.setSource("B");
        order.setCreateTime(new Date());
        moOrderMapper.insertSelective(order);
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHH");
        DecimalFormat df=new DecimalFormat("000000");
        String orderNo=sdf.format(new Date())+df.format(order.getOrderId());
        MoOrder uporder=new MoOrder();
        uporder.setOrderId(order.getOrderId());
        uporder.setOrderCode(orderNo);
        moOrderMapper.updateByPrimaryKeySelective(uporder);
        return MAIN_HOST+"wappage/buspage/linkagePay/"+order.getOrderId().toString();
    }

    @Override
    public void payCallBack(Long orderId, Double amount, Double fee, String paystatus) throws PassagewayException {
        MoOrder order=moOrderMapper.selectByPrimaryKey(orderId);
        if (order.getStatus().equals(3)) {
            return;
        }
        if (!paystatus.equals("Y")) {
            return;
        }
        MoOrder updateOrder=new MoOrder();
        updateOrder.setFee(MoneyUtil.formatMoney(fee));
        updateOrder.setStatus(3);
        updateOrder.setOrderId(orderId);
        moOrderMapper.updateByPrimaryKeySelective(updateOrder);

        order.setStatus(3);
        order.setFee(updateOrder.getFee());

        String settlementFee= MoneyUtil.formatMoney(amount-fee);
        //结算记录走一波
        MoSettlement settlement=new MoSettlement();
        settlement.setOrderId(orderId);
        settlement.setSettlementTime(new Date());
        settlement.setMoney(settlementFee);
        //得到开户行信息
        //查出付款主体账户
        MoPassagewayAccount account=moPassagewayAccountMapper.selByUserId(order.getUserId(),passagewayId);
        settlement.setBankName(account.getBankName());
        settlement.setBankNumber(account.getBankNumber());
        settlement.setStatus(2);
        SimpleDateFormat sdf=new SimpleDateFormat("yMMddHHmmss");
        DecimalFormat df=new DecimalFormat("000000");
        settlement.setSettlementCode(sdf.format(new Date())+df.format(order.getOrderId()));
        settlement.setCashMoney(account.getCashMoney());
        moSettlementMapper.insertSelective(settlement);
        //分润走一波
        toMakeProfit(settlement.getSettlementId(),order);
    }

    /**
     * 给代理分润
     * @param settlementId
     * @throws LinkageException
     */
    public void toMakeProfit(Long settlementId,MoOrder order) throws LinkageException {

        //代理费率
        SettleRate settAgentRate=managerUserMapper.selAgentRateBySettleId(settlementId,passagewayId);
        if (settAgentRate == null) {
            settAgentRate=managerUserMapper.selAgentRateBySettleId(settlementId,1L);
            if (settAgentRate!=null) {
                settAgentRate.setRate(settAgentRate.getRate()-0.001d);
            }else{
                throw new LinkageException(order.getOrderId()+"_取代理分润信息失败");
            }
        }
        Double agentRate=settAgentRate.getRate();
        if (agentRate == null||agentRate<systemRate) {
            agentRate=systemRate;
        }
        //实际手续费-代理的成本手续费=代理的利润
        Double profitMoney=Double.valueOf(order.getFee())-Double.valueOf(settAgentRate.getTradeMoney())*agentRate;
        if (profitMoney>0) {//如果等于0就没什么好分的啦
            //加余额
            try {
                agentProcess.increaseProfile(settAgentRate.getUserId(),profitMoney);
            } catch (AgentException e) {
                throw new LinkageException(e.getMessage());
            }
        }else{
            profitMoney=0d;
        }
        MoShareProfit profit=new MoShareProfit();
        profit.setAgentId(settAgentRate.getUserId());
        profit.setBusinessId(order.getUserId());
        profit.setCreateTime(new Date());
        profit.setOrderId(settAgentRate.getOrderId());
        profit.setTradeMoney(settAgentRate.getTradeMoney());
        profit.setProfitMoney(profitMoney.toString());
        profit.setCostRate(order.getRate());
        DecimalFormat df=new DecimalFormat("0.0000");
        profit.setAgentRate(df.format(agentRate));
        moShareProfitMapper.insertSelective(profit);

        if (profitMoney<=0) {
            return;
        }

        ManagerUser user=managerUserMapper.selectByPrimaryKey(order.getUserId());

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //发送分润提醒，先查出代理openid如果 没有则不发
        MoWxuserinfoExample wxExample=new MoWxuserinfoExample();
        wxExample.createCriteria().andUserIdEqualTo(settAgentRate.getUserId());
        wxExample.setStartIndex(0);
        wxExample.setEndIndex(1);
        List<MoWxuserinfo> wxinfos=moWxuserinfoMapper.selectByConditionList(wxExample);
        Map<String,WxTempleateBaseData> wxTempleateDataMap=new HashMap<>();
        wxTempleateDataMap.put("first",new WxTempleateBaseData("恭喜你，获得一笔分润佣金！"));
        wxTempleateDataMap.put("keyword1",new WxTempleateBaseData(MoneyUtil.formatMoney(profitMoney)));
        wxTempleateDataMap.put("keyword2",new WxTempleateBaseData(sdf.format(new Date())));
        wxTempleateDataMap.put("remark",new WxTempleateBaseData(SecretUtil.secretName(user.getRealName()) +
                "消费了"+MoneyUtil.formatMoney(order.getMoney())+"元"));
        String targetopenid="";
        if (wxinfos.size()>0) {
            MoWxuserinfo wxuser=wxinfos.get(0);
            try {
                String token=wxTokenService.getSystemToken().getAccess_token();
                wxTokenService.sendTemplateMsg(PAYED_NOTIFY,wxuser.getOpenId(),wxTempleateDataMap,MAIN_HOST+"wappage/agpage/tradeDetail",token);
                targetopenid=wxuser.getOpenId();
            } catch (Exception e) {
                logger.error("获取token失败",e);
            }
        }
        //发给老赵一份
        if (!ADMIN_NOTIFY.equals(targetopenid)) {
            wxTempleateDataMap.put("first",new WxTempleateBaseData("恭喜["+settAgentRate.getUserId()+"]，获得一笔分润佣金！","#9E272A"));
            try {
                String token=wxTokenService.getSystemToken().getAccess_token();
                wxTokenService.sendTemplateMsg(PAYED_NOTIFY,ADMIN_NOTIFY,wxTempleateDataMap,MAIN_HOST+"wappage/agpage/tradeDetail",token);
            } catch (Exception e) {
                logger.error("发消息失败",e);
            }
        }
    }


    @Override
    public void setFee(Long agentId, Long businessId, Double rate, Double settleMoney) throws PassagewayException {
        rate=rate/100;
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(agentId).andPassagewayIdEqualTo(passagewayId);
        accountExample.setStartIndex(0);
        accountExample.setEndIndex(1);
        List<MoPassagewayAccount> ageentunpays=moPassagewayAccountMapper.selectByConditionList(accountExample);
        Double limitRate=systemRate;
        if (ageentunpays.size()>0) {
            limitRate=Double.valueOf(ageentunpays.get(0).getRate());
        }
        superSetFee(businessId,rate,limitRate,settleMoney);
    }

    @Override
    public void superSetFee(Long userId, Double rate, Double limitRate, Double settleMoney) throws PassagewayException {
        if(rate<limitRate){
            new LinkageException("商户费率不能小于代理费率").throwMe();
        }
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(userId).andPassagewayIdEqualTo(passagewayId);
        accountExample.setStartIndex(0);
        accountExample.setEndIndex(1);
        MoPassagewayAccount unpay=moPassagewayAccountMapper.selectByConditionList(accountExample).get(0);
        DecimalFormat df=new DecimalFormat("0.0000");
        ResetRateRequest mrr=new ResetRateRequest();
        mrr.setSubMerchantCode(unpay.getAccountCode());
        mrr.setMerchantCode(merchantCode);
        String rateStr=df.format(rate);
        mrr.setTradeRate(rateStr);
        mrr.setFastpayRate(rateStr);
        ResetRateResponse res=mrr.exec();
        if (!res.isSuccess()) {
            throw new LinkageException(res.getErrorMessage());
        }
        MoPassagewayAccount updateAccount=new MoPassagewayAccount();
        updateAccount.setRate(rate.toString());
        if (settleMoney != null) {
            updateAccount.setCashMoney(MoneyUtil.formatMoney(settleMoney));
        }
        moPassagewayAccountMapper.updateByExampleSelective(updateAccount,accountExample);
    }

    @Override
    public Double getSystemRate() {
        return null;
    }
}
